﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SharpMUD.Framework.IO
{
    public sealed class PersistanceProxy<T>
    {
        protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(SharpMUD.Framework.ComponentModel.IService).Assembly, System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);

        private PersistanceProxy() { }
        public PersistanceProxy(Func<T> loadFunc, Action<T> saveAction)
        {
            this.Load = loadFunc;
            this.Save = saveAction;
        }

        public Action<T> Save
        {
            get;
            private set;
        }

        public Func<T> Load
        {
            get;
            private set;
        }

        public static PersistanceProxy<T> InMemory(T item, bool throwExceptionOnPersistAttempt)
        {
            return new PersistanceProxy<T>(
                delegate()
                {
                    return item;
                }
                    ,
                delegate(T i)
                {
                    if (throwExceptionOnPersistAttempt)
                        throw new InvalidOperationException();
                }
                );
        }

        public static PersistanceProxy<T> XmlSerializationString(string inputXml, StringWriter outputXmlWriter)
        {
            return new PersistanceProxy<T>(
                delegate()
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    var result = default(T);
                    using (TextReader textReader = new StringReader(inputXml))
                    {
                        result = (T)serializer.Deserialize(textReader);
                    }
                    return result;
                }
                    ,
                delegate(T i)
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    TextWriter textWriter = outputXmlWriter;
                    serializer.Serialize(textWriter, i);
                }
                );
        }

        public static PersistanceProxy<T> DefaultOrXmlSerializationFile(string fileName, T defaultValue, Action signalDefaultUsed)
        {
            return new PersistanceProxy<T>(
                delegate()
                {
                    try
                    {
                        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                        var result = default(T);
                        using (TextReader textReader = new StreamReader(fileName, System.Text.Encoding.Default))
                        {
                            result = (T)serializer.Deserialize(textReader);
                        }
                        return result;
                    }
                    catch (FileNotFoundException e)
                    {
                        log.WarnFormat("Could not open \"{0}\" - file not found", fileName);
                        if (!(signalDefaultUsed == null))
                            signalDefaultUsed();
                        return defaultValue;
                    }
                    catch (DirectoryNotFoundException e)
                    {
                        log.WarnFormat("Could not open \"{0}\" - directory not found", fileName);
                        if (!(signalDefaultUsed == null))
                            signalDefaultUsed();
                        return defaultValue;
                    }
                    catch (System.Exception e)
                    {
                        log.Warn("Could not open \"{0}\"", e);
                        if (!(signalDefaultUsed == null))
                            signalDefaultUsed();
                        return defaultValue;
                    }
                }
                    ,
                delegate(T i)
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    using (TextWriter textWriter = new StreamWriter(fileName, false, System.Text.Encoding.Default))
                    {
                        serializer.Serialize(textWriter, i);
                    }
                }
            );
        }

        public static PersistanceProxy<T> XmlSerializationFile(string fileName)
        {
            return new PersistanceProxy<T>(
                delegate()
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    var result = default(T);
                    using (TextReader textReader = new StreamReader(fileName, System.Text.Encoding.Default))
                    {
                        result = (T)serializer.Deserialize(textReader);
                    }
                    return result;
                }
                    ,
                delegate(T i)
                {
                    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    using (TextWriter textWriter = new StreamWriter(fileName, false, System.Text.Encoding.Default))
                    {
                        serializer.Serialize(textWriter, i);
                    }
                }
                );
        }
    }
}
